package com.pks.datacenter.aspect;

import io.swagger.annotations.Api;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.pks.datacenter.common.WebContext;
import com.pks.datacenter.config.RedisKeyConfig;
import com.pks.datacenter.config.RequestHolder;
import com.pks.datacenter.entity.api.ApiLog;
import com.pks.datacenter.entity.api.ApiMethod;
import com.pks.datacenter.entity.api.ApiToken;
import com.pks.datacenter.handler.RedisHandler;
import com.pks.datacenter.service.api.ApiLogService;
import com.pks.datacenter.service.api.ApiMethodService;
import com.pks.datacenter.service.api.ApiRecordService;
import com.pks.datacenter.service.api.ApiTokenService;
import com.pks.datacenter.service.api.ApiUserService;
import com.pks.resultful.common.SRemoteResult;
import com.pks.util.SUtilDate;
 
/**
 * 操作日志切面定义
 */
@Aspect
@Component
public class ApiLogApsect {
    
    @SuppressWarnings("unused")
	private static Logger logger = LoggerFactory.getLogger(ApiLogApsect.class);
    
//    private long currentTime = 0L;

    @Pointcut("@annotation(com.pks.datacenter.aspect.AspectApiLogTag)")
    public void logPointcut() {
        
    }
    
    @Autowired
    private ApiLogService apiLogService;
    @Autowired
    private ApiMethodService apiMethodService;
    @Autowired
    private ApiTokenService apiTokenService;
    @Autowired
    private ApiUserService apiUserService;
    @Autowired
    private ApiRecordService apiRecordService;
    @Autowired
    private RedisHandler redisHandler;
    
    private List<Integer> excludes = Arrays.asList(new Integer[]{30001,30002});
    

    /**
     *  配置环绕通知
     * @param joinPoint
     * @return
     * @throws Throwable
     */
    @SuppressWarnings("rawtypes")
	@Around("logPointcut()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
    	try {
    		Object result;
    		Long currentTime = System.currentTimeMillis();
    		result = joinPoint.proceed();
    		long time = System.currentTimeMillis() - currentTime;
    		SRemoteResult sr = (SRemoteResult) result;
    		if (!excludes.contains(sr.getS())) {
    			save(joinPoint,sr,time);
    		}
    		return sr;
		} catch (Exception e) {
			e.printStackTrace();
		}
    	return null;
    }

    @SuppressWarnings({ "rawtypes", "unused" })
	private void save(ProceedingJoinPoint joinPoint,SRemoteResult sr,Long time) {
    	try {
    		HttpServletRequest request = RequestHolder.getHttpServletRequest();
//    	User logined = WebContext.getLoginUser(request);
    		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
    		Api api = joinPoint.getTarget().getClass().getAnnotation(Api.class);
    		
    		Method method = signature.getMethod();
    		AspectApiLogTag tag =  method.getAnnotation(AspectApiLogTag.class);
    		List<String> saveParams = new ArrayList<String>();
    		if (tag.params() != null && tag.params().length > 0) {
    			saveParams = Arrays.asList(tag.params());
    		}
    		// 方法路径
    		String methodName = joinPoint.getTarget().getClass().getName()+"."+signature.getName()+"()";
    		StringBuilder params = new StringBuilder("{");
    		Map<String, Object> paramsMap = new HashMap<String, Object>();
    		// 参数值
    		Object[] argValues = joinPoint.getArgs();
    		// 参数名称
    		String[] argNames = ((MethodSignature)joinPoint.getSignature()).getParameterNames();
    		if (argValues != null){
    			for (int i = 0; i < argValues.length; i++) {
    				if (saveParams.size() > 0) {
    					if (saveParams.contains(argNames[i])) {
    						paramsMap.put(argNames[i], argValues[i]);
    						params.append(" ").append(argNames[i]).append(": ").append(argValues[i]);    
    					}
    				} else {
    					if (!argNames[i].equals("request")) {
    						if (argValues[i] != null) {
    							paramsMap.put(argNames[i], argValues[i]);
    							params.append(" ").append(argNames[i]).append(": ").append(argValues[i]);            			
    						}
    					}
    				}
    			}
    		}
    		
    		boolean isGetToken = tag.isGetToken();
    		String apiMethodName = "";
    		Long apiUserId = null;
    		String apiUserAccount = "";
    		Long apiId = null;
    		if (isGetToken) {
    			apiMethodName = "getApiToken";
    			apiUserAccount = paramsMap.get("account")==null?"":paramsMap.get("account").toString();
    			if (sr.success()) {
    				ApiToken apiTokenShow = (ApiToken)sr.getD();
    				String apiToken = apiTokenShow.getApiToken();
    				ApiToken apiTokenObj = apiTokenService.findByToken(apiToken); 
    				if (apiTokenObj != null) {
    					apiUserId = apiTokenObj.getApiUserId();
    				}
    			}
    		} else {
    			apiMethodName = paramsMap.get("methodName")==null?"":paramsMap.get("methodName").toString();
    			String apiToken = paramsMap.get("apiToken")==null?"":paramsMap.get("apiToken").toString();
    			if (StringUtils.isNotBlank(apiToken)) {
    				ApiToken apiTokenObj = apiTokenService.findByToken(apiToken); 
    				if (apiTokenObj != null) {
    					apiUserId = apiTokenObj.getApiUserId();
    					apiUserAccount = apiTokenObj.getApiUserAccount();
    				}
    			}
    		}
    		ApiMethod apiMethod = apiMethodService.findByMethodName(apiMethodName);
    		if (apiMethod != null) {
    			apiId = apiMethod.getId();
    		}
    		ApiLog log = new ApiLog();
    		log.insertBefore();
    		log.setApiUserId(apiUserId);
    		log.setApiUserAccount(apiUserAccount);
    		log.setApiId(apiId);
    		log.setApiMethodName(apiMethodName);
    		log.setParams(JSON.toJSONString(paramsMap));
    		log.setRequestIp(WebContext.getRealIpAddress(request));
    		log.setRequestUrl(request.getRequestURL().toString());
    		log.setResultState(sr.getS());
    		if (sr.success()) {
    			if (sr.getD() instanceof List) {
    				List list = (List)sr.getD();
    				log.setResultContent("获取数据" + list.size() + "条");
    			} else {
    				log.setResultContent(sr.getD()==null?"":sr.getD().toString());
    			}
    		} else {
    			log.setResultContent(sr.getMsg());
    		}
    		if (StringUtils.isNotBlank(log.getParams()) && log.getParams().length() > 2000) {
    			log.setParams(log.getParams().substring(0, 2000));
    		}
    		if (StringUtils.isNotBlank(log.getResultContent()) && log.getResultContent().length() > 2000) {
    			log.setResultContent(log.getResultContent().substring(0, 2000));
    		}
    		log.setTime(time);
    		apiLogService.insert(log);
//    		if (sr.success()) {
//    			String time_sdf = SUtilDate.SDF_DATE_NOSEP.get().format(new Date());
//    			String key = RedisKeyConfig.KEY_API_RECORD + time_sdf + ":" + log.getApiUserAccount() + "_" + apiMethodName;
//    			if (redisHandler.hasKey(key)) {
//    				redisHandler.incr(key, 1);
//    			} else {
//    				redisHandler.set(key , 1, 24 * 60 * 3600);
//    			}
//    			redisHandler.set(RedisKeyConfig.KEY_API_LASTUSETIME + apiUserAccount + "_" + apiMethodName, new Date().getTime());
//            	ApiRecord record = new ApiRecord();
//    			record.insertBefore();
//    			record.setApiUserId(log.getApiUserId());
//    			record.setApiUserAccount(log.getApiUserAccount());
//    			record.setApiId(log.getApiId());
//    			record.setApiMethodName(log.getApiMethodName());
//    			apiRecordService.insert(record);
//    		}
		} catch (Exception e) {
			e.printStackTrace();
		}
        
	}

//	  /**
//     *  配置异常通知
//     * @param joinPoint
//     * @param e
//     */
//    @AfterThrowing(pointcut = "logPointcut()",throwing = "e")
//    public void logAfterThrowing(JoinPoint joinPoint,Throwable e){
//       SystemOperLog log = new SystemOperLog("ERROR",System.currentTimeMillis() - currentTime);
//       log.setExceptionDetail(ThrowableUtil.stackTraceToString(e.getClass().getName(),e.getMessage(),e.getStackTrace()));
//       HttpServletRequest request = RequestHolder.getHttpServletRequest();
//       xtLogService.save(getUsername(),StringUtils.getBrowser(request),StringUtils.getIp(request),request.getRequestURI(), (ProceedingJoinPoint) joinPoint,log);
//    }

 
    
}
 